package com.core.family.gen.service.gen.Impl;


import cn.hutool.core.date.DateUtil;
import com.core.common.utils.SqlColumnConvertUtil;
import com.core.family.gen.config.GenProperties;
import com.core.family.gen.config.GenConfManger;
import com.core.family.gen.domain.po.TableBeanPo;
import com.core.family.gen.domain.po.TableColumnPo;
import com.core.family.gen.service.gen.ITemplateGenService;
import com.core.family.gen.service.gen.IGenHandler;
import com.core.common.utils.springutils.ApplicationUtil;
import lombok.Data;
import org.springframework.util.StringUtils;

import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: honglei
 * @time: 2021/3/26 0026 14:50
 */
@Data
public abstract class AbsGenHandler implements IGenHandler {

    public GenProperties properties;


    protected GenConfManger config;

    private ITemplateGenService templateGenService;

    public ITemplateGenService getTemplateGen() {
        if (null == templateGenService) {
            templateGenService = ApplicationUtil.getBean(ITemplateGenService.class);
        }
        return templateGenService;
    }


    public Connection getConnection() throws Exception {
        Properties props = new Properties();
        props.put("user", getConfig().getUserName());
        props.put("password", getConfig().getPasswd());
        props.put("useInformationSchema", "true"); //表注释
        Class.forName(getConfig().getDriver());
        String dbUrl = getConfig().getUrl();
        Connection connection = DriverManager.getConnection(dbUrl, props);
        return connection;
    }


    @Override
    public boolean genCode(List<TableBeanPo> tableNames) throws Exception {
        boolean flag = false;
        for (TableBeanPo tableName : tableNames) {
            flag = genCode(tableName);
        }
        return flag;
    }

    @Override
    public boolean genCode(TableBeanPo tableBean) throws Exception {
        tableBean.setTableColumnPoList(getColumns(tableBean.getTableName()));
        if (StringUtils.isEmpty(tableBean.getClassName())) {
            tableBean.setClassName(tableToJava(tableBean.getTableName(), ""));
        }

        String allSqlcolum = tableBean.getTableColumnPoList()
                .stream().map(bean -> {
                    return bean.getColumnName();
                }).collect(Collectors.joining(","));
        tableBean.setAllSqlColumn(allSqlcolum);


        generateModelFile(tableBean);
        generateModelDtoFile(tableBean);
        generateMapperFile(tableBean);
        generateMapperXMLFile(tableBean);

        generateServiceInterfaceFile(tableBean);
        generateServiceImplFile(tableBean);
        generateControllerFile(tableBean);
//
        generateMapperJsFile(tableBean);
        generateMapperViewFile(tableBean);
        return true;
    }


    protected List<TableColumnPo> filledTableColumn(ResultSet resultSet) throws Exception {
        List<TableColumnPo> list = new ArrayList<>();
        while (resultSet.next()) {
            TableColumnPo columnBean = new TableColumnPo();
            columnBean.setColumnName(resultSet.getString("COLUMN_NAME"));
            columnBean.setColumnType(resultSet.getString("TYPE_NAME").toUpperCase());
            columnBean.setComments(resultSet.getString("REMARKS"));
            columnBean.setAttrname(SqlColumnConvertUtil.convertToAttributeType(columnBean.getColumnName()));
            list.add(columnBean);
        }
        resultSet.close();
        return list.stream().distinct().collect(Collectors.toList());
    }


    protected List<TableBeanPo> filledTableBean(ResultSet rs) throws Exception {
        List<TableBeanPo> list = new ArrayList<>();
        while (rs.next()) {
            TableBeanPo tableBean = new TableBeanPo();
            tableBean.setTableName(rs.getString("TABLE_NAME"));
            tableBean.setComments(rs.getString("REMARKS"));
            tableBean.setClassName(tableToJava(tableBean.getTableName(), getConfig().getBaseConf().getTablePrefix()));
            tableBean.setClassNameSub(SqlColumnConvertUtil.convertToAttributeType(tableBean.getTableName()));
            list.add(tableBean);
        }
        rs.close();
        return list.stream().distinct().collect(Collectors.toList());
    }


    private void generateModelFile(TableBeanPo tableBean) throws Exception {
        String suffix = tableBean.getClassName() + ".java";
        String path = getConfig().getBaseConf().getDiskPath() + getConfig().getPackagePath() + "\\domain\\" + suffix;
        File file = new File(path);
        getTemplateGen().generateFileByTemplate("Model.ftl", file, getDataMap(tableBean));
    }

    private void generateModelDtoFile(TableBeanPo tableBean) throws Exception {
        String suffix = tableBean.getClassName() + "Req.java";
        String path = getConfig().getBaseConf().getDiskPath() + getConfig().getPackagePath() + "\\domain\\req\\" + suffix;
        File file = new File(path);
        getTemplateGen().generateFileByTemplate("ModelReq.ftl", file, getDataMap(tableBean));
    }


    private void generateMapperFile(TableBeanPo tableBean) throws Exception {
        String suffix = tableBean.getClassName() + "Mapper.java";
        String path = getConfig().getBaseConf().getDiskPath() + getConfig().getPackagePath() + "\\mapper\\" + suffix;
        File file = new File(path);
        getTemplateGen().generateFileByTemplate("Mapper.ftl", file, getDataMap(tableBean));
    }

    private void generateMapperXMLFile(TableBeanPo tableBean) throws Exception {
        String suffix = tableBean.getClassName() + "Mapper.xml";
        String path = getConfig().getBaseConf().getDiskPath() + "/" + suffix;
        File file = new File(path);
        getTemplateGen().generateFileByTemplate("MapperXml.ftl", file, getDataMap(tableBean));
    }


    private void generateServiceInterfaceFile(TableBeanPo tableBean) throws Exception {
        String suffix = tableBean.getClassName() + "Service.java";
        String path = getConfig().getBaseConf().getDiskPath() + getConfig().getPackagePath() + "\\service\\" + suffix;
        File file = new File(path);
        getTemplateGen().generateFileByTemplate("Service.ftl", file, getDataMap(tableBean));
    }

    private void generateServiceImplFile(TableBeanPo tableBean) throws Exception {
        String suffix = tableBean.getClassName() + "ServiceImpl.java";
        String path = getConfig().getBaseConf().getDiskPath() + getConfig().getPackagePath() + "\\service\\Impl\\" + suffix;
        File file = new File(path);
        getTemplateGen().generateFileByTemplate("ServiceImpl.ftl", file, getDataMap(tableBean));
    }


    private void generateControllerFile(TableBeanPo tableBean) throws Exception {
        String suffix = tableBean.getClassName() + "Controller.java";
        String path = getConfig().getBaseConf().getDiskPath() + getConfig().getPackagePath() + "\\controller\\" + suffix;
        File file = new File(path);
        getTemplateGen().generateFileByTemplate("Controller.ftl", file, getDataMap(tableBean));
    }

    private void generateMapperJsFile(TableBeanPo tableBean) throws Exception {
        String suffix = tableBean.getClassNameSub() + ".js";
        String path = getConfig().getBaseConf().getDiskPath() + "/resources/api/" + suffix;
        File file = new File(path);
        getTemplateGen().generateFileByTemplate("vue-js.ftl", file, getDataMap(tableBean));
    }

    private void generateMapperViewFile(TableBeanPo tableBean) throws Exception {
        String suffix = tableBean.getClassNameSub() + ".vue";
        String path = getConfig().getBaseConf().getDiskPath() + "/resources/views/" + suffix;
        File file = new File(path);
        getTemplateGen().generateFileByTemplate("vue-view.ftl", file, getDataMap(tableBean));
    }

    /***
     * 生成传输到模板的数据
     * @param tableBean
     * @return
     */
    private Map<String, Object> getDataMap(TableBeanPo tableBean) {
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("packageName", getConfig().getBaseConf().getPackageName());
        dataMap.put("dateTime", DateUtil.now());
        dataMap.put("comments", tableBean.getComments());
        dataMap.put("tableName", tableBean.getTableName());
        dataMap.put("poName", tableBean.getClassName());
        dataMap.put("classNameSub", tableBean.getClassNameSub());
        dataMap.put("columnBeanList", tableBean.getTableColumnPoList());
        dataMap.put("allSqlColumn", tableBean.getAllSqlColumn());
        return dataMap;
    }


}
